Chapter 3: Offline Authorization Protocol
This chapter defines the complete lifecycle protocol flow of Authorization_Descriptor, including the five stages of issuance, local storage, validation, revocation, and renewal. The flow in this chapter corresponds to the design intent in §2.1 of the blueprint.
3.1 Issuance Flow
The issuance flow is executed by Descriptor_Issuer after receiving explicit authorization from the authorizer. This specification defines the format constraints of the issuance result but does not prescribe the specific interaction between the authorizer and Descriptor_Issuer (different deployments may adopt different forms such as web forms, mobile App authorization, enterprise authorization management systems, etc.).
3.1.1 Issuance Input
At the time of issuance, Descriptor_Issuer MUST have already confirmed the following information:
- The authorizer's identity (
grantor_id) has passed Descriptor_Issuer's own identity verification mechanism - The authorization scope (target
subject_fay_id,terminal_id,grants) is explicitly specified by the authorizer - The validity period (
not_before,not_after) is explicitly specified by the authorizer or follows a default policy
3.1.2 Issuance Steps
Descriptor_Issuer MUST generate Authorization_Descriptor following these steps:
- Generate identifier: Allocate a new
descriptor_id(UUID v7); MUST NOT reuse a previously used ID - Construct payload: Fill in
DescriptorPayloadper §2.3.2; all required fields MUST be set - Validate constraints: Locally validate constraints such as
not_after - not_before ≤ 90 days(see §2.3.2) - CBOR serialization: Serialize the payload using RFC 8949 deterministic encoding
- Digital signature: Sign the payload bytes using the Descriptor_Issuer private key with the algorithm defined in §8
- Assemble structure: Construct the complete
AuthorizationDescriptor, including version, payload, and signature - Register record: Register the credential in Descriptor_Issuer's internal state store (for subsequent revocation management)
3.1.3 Post-Issuance Delivery
After issuance is complete, Descriptor_Issuer delivers Authorization_Descriptor to the target Fay. The delivery method is outside the scope of this specification, but SHOULD satisfy:
- Delivery via an encrypted channel to avoid interception of the credential during transmission
- Delivery to the
iFay_Runtimeto which the Fay belongs, with iFay_Runtime holding it on behalf of the Fay
3.2 Local Storage Flow
Fay submits Authorization_Descriptor to the target terminal through iFay_Runtime for local storage.
3.2.1 Submission Message
iFay_Runtime sends a DescriptorSubmit message to Protocol_Engine:
DescriptorSubmit (body of ProtocolMessage) {
required descriptor : AuthorizationDescriptor
}
3.2.2 Terminal Processing
After receiving DescriptorSubmit, the terminal MUST process it in the following order:
- Structural validation: Verify that
descriptorconforms to the structure defined in §2.3 - Signature validation: Verify the signature using the Verification_Key corresponding to
key_id(see §3.3.4) - Deduplication check: If a credential with the same
descriptor_idis already stored locally and the newly submitted content matches the stored content byte-for-byte, return success; otherwise reject with a duplicate ID error - Storage: Encrypt and store the Authorization_Descriptor in the local secure storage area (see §3.2.3)
- Return result: Return a
DescriptorSubmitResultmessage to iFay_Runtime, containing success or an error code
3.2.3 Storage Requirements
The terminal MUST:
- Store Authorization_Descriptor encrypted; the encryption key MUST NOT be readable by unauthorized processes
- The storage medium SHOULD have anti-physical-tampering capability (e.g., secure chip, TEE)
- The storage capacity ceiling SHOULD be no fewer than 1024 credentials; when the ceiling is exceeded, expired credentials are evicted using LRU policy
The terminal MUST NOT:
- Store Authorization_Descriptor in plaintext form
- Modify any field of the descriptor before storage (including metadata)
3.2.4 Error Codes
| Error Code | Trigger Condition |
|---|---|
E_INVALID_STRUCTURE | Structure does not conform to §2.3 |
E_INVALID_SIGNATURE | Signature validation failed |
E_UNKNOWN_ISSUER | The Verification_Key corresponding to key_id is not registered on the terminal |
E_DUPLICATE_DESCRIPTOR_ID | Conflict with stored descriptor_id with mismatching content |
E_STORAGE_FULL | Storage capacity is full and no eviction is possible |
E_VALIDITY_OUT_OF_RANGE | not_after - not_before exceeds the limit |
3.3 Validation Flow
The validation flow is executed on each resource access request. This section defines the complete steps and decision rules for validation.
3.3.1 Validation Trigger
When iFay_Runtime sends an AuthRequest requesting resource access, the terminal Protocol_Engine triggers the validation flow:
AuthRequest (body of ProtocolMessage) {
required fay_id : Fay_ID
required resource_id : Resource_ID
required access_mode : AccessMode
required credential : CredentialReference
}
CredentialReference {
required type : enum["descriptor", "ticket"]
required id : string // descriptor_id or jti
}
Note: In the offline authorization scenario of this specification, credential references an Authorization_Descriptor already stored on the terminal; there is no need to transmit the complete credential in the request.
3.3.2 Validation Steps (Executed in Order)
The terminal MUST execute validation in the following order. Failure at any step immediately returns the corresponding error code without proceeding to subsequent steps.
Step 1: Credential Existence
The terminal looks up the Authorization_Descriptor corresponding to credential.id in local storage.
- Not found → return
E_DESCRIPTOR_NOT_FOUND
Step 2: Revocation Status
The terminal checks the local revocation list to confirm that the descriptor_id has not been revoked.
- Revoked → return
E_DESCRIPTOR_REVOKED
Step 3: Validity Period
The terminal checks that the current time is within the [not_before, not_after] interval.
- Current time <
not_before→ returnE_DESCRIPTOR_NOT_YET_VALID - Current time ≥
not_after→ returnE_DESCRIPTOR_EXPIRED
Terminal clock source: MUST use a calibrated system clock. The terminal SHOULD handle validation requests cautiously when not online for extended periods (see §3.6 Clock Drift Handling).
Step 4: Subject Match
The terminal verifies that payload.subject_fay_id == AuthRequest.fay_id.
- Mismatch → return
E_SUBJECT_MISMATCH
Step 5: Terminal Match
The terminal verifies that payload.terminal_id == current terminal ID.
- Mismatch → return
E_TERMINAL_MISMATCH
Step 6: Resource and Mode Match
The terminal iterates over payload.grants and looks for a Grant satisfying:
Grant.resource_patternmatchesAuthRequest.resource_idper §2.3.5 rulesGrant.modescontainsAuthRequest.access_mode- If
Grant.constraintsis not empty, all constraints are satisfied (see §7.4 for constraint semantics)
- No matching Grant found → return
E_AUTHORIZATION_INSUFFICIENT
Step 7: Signature Validation
The terminal re-validates the payload's signature using the Verification_Key corresponding to signature.key_id.
Note: The fast checks of steps 1–6 are completed before signature validation, providing reasonable failure semantics (e.g., reporting "credential revoked" before "signature failed"). However, signature validation MUST have been executed and passed before validation passes and success is returned.
- Signature validation failed → return
E_INVALID_SIGNATURE - Signing key revoked or expired → return
E_VERIFICATION_KEY_INVALID
3.3.3 After Validation Passes
After all 7 steps pass, the terminal creates a Session per the flow in Chapter 5 and returns to iFay_Runtime:
AuthResult (body of ProtocolMessage, success) {
required status : "granted"
required session_id : Session_ID
required granted_modes : array<AccessMode>
required session_expires_at : timestamp
}
session_expires_at SHOULD equal min(not_after, current time + default maximum session duration).
3.3.4 Signature Validation Details
Specific steps of signature validation:
- Extract
descriptor.signature.key_idand look up the corresponding public key in the terminal's Verification_Key store - Verify that the Verification_Key is valid at the current time (
valid_from ≤ current time ≤ valid_until, if valid_until is set) - Re-CBOR-serialize
descriptor.payloadper §2.3.3 rules - Verify the signature of the serialized bytes using the Verification_Key and
descriptor.signature.algorithm - After successful validation, MUST cache the result (the same descriptor only requires signature validation once during its lifecycle)
3.4 Revocation Flow
3.4.1 Revocation Initiation
The authorizer initiates a revocation request through Descriptor_Issuer. The specific interaction form for revocation requests is outside the scope of this specification.
After receiving a revocation request, Descriptor_Issuer MUST:
- Verify that the revocation request is from the original authorizer or an entity with revocation authority
- Generate a
RevocationStatementper §2.8 - Sign the revocation statement with the same signing key used for the original Authorization_Descriptor
- Add the revocation statement to the revocation list maintained by Descriptor_Issuer
3.4.2 Revocation Distribution
Revocation statements are distributed to terminals through the following methods; the terminal MUST support at least two of them:
- Pull-based synchronization: When online, the terminal proactively pulls incremental revocation lists from Descriptor_Issuer or a revocation service. Synchronization frequency is determined by terminal policy and SHOULD be no less than once per hour (during online periods)
- Push-based notification: Descriptor_Issuer pushes revocation statements to the terminal via Registration_Authority or a dedicated revocation distribution service
- In-band embedding: A digest of the recent revocation list is carried in the Trusted_Ticket metadata, allowing tickets obtained while online to automatically carry revocation information
3.4.3 Terminal Revocation List Maintenance
The terminal's local revocation list MUST:
- Permanently store all unexpired revocation statements
- After a credential's
not_aftertime has passed, MAY delete the corresponding revocation statement (the credential has expired naturally) - Validate the signature of each revocation statement and reject revocation statements with invalid signatures
3.4.4 Revocation Effective Time
The effective time of a revocation statement is:
Effective time = max(time the revocation statement reaches the terminal, RevocationStatement.revoked_at)
The terminal MUST ensure that subsequent validation requests after a revocation statement reaches the terminal immediately reject the credential. The terminal MAY proactively check whether all active Sessions reference revoked credentials and, if so, forcibly terminate those Sessions per the rules in Chapter 5.
3.4.5 Revocation Delay Window
Due to the inherent delay of offline distribution, the following unavoidable revocation delay windows exist:
| Scenario | Maximum Delay |
|---|---|
| Terminal continuously online | One synchronization cycle (default ≤ 1 hour) |
| Terminal briefly offline | Next synchronization after reconnection |
| Terminal long-term offline | Maximum delay is the credential's not_after - revocation time, but no more than 90 days (the maximum credential validity period) |
Issuers SHOULD limit the maximum revocation delay by setting shorter not_after values (e.g., 7 days).
3.5 Renewal Flow
Renewal is essentially the issuance of a new Authorization_Descriptor to replace the old version, not a modification of the existing credential.
3.5.1 Renewal Policy
The authorizer or an automatic renewal mechanism may trigger renewal in the following scenarios:
- The credential is approaching
not_afterand the authorization relationship is still valid - The authorization scope needs to be adjusted (adding/removing grants)
- The authorization constraints need to be adjusted (modifying constraints)
3.5.2 Renewal Flow
Renewal process:
- Descriptor_Issuer issues a new Authorization_Descriptor following the §3.1 flow, using a new
descriptor_id - The new credential is submitted to the terminal and stored following the §3.2 flow
- The old credential MAY be proactively revoked by the issuer (per §3.4) or MAY expire naturally
During the period when both new and old credentials coexist, the terminal's processing priorities are:
- Validation requests MUST preferentially match unexpired credentials
- When multiple unexpired credentials all match, the credential with the most recent
issued_atis used
3.5.3 Disallowed Renewal Behaviors
Implementations MUST NOT:
- Modify any field of an issued credential (including metadata)
- Reuse the
descriptor_idof an old credential - Modify the semantics of an old credential while it is still valid (must be done through revocation + new issuance)
3.6 Clock Drift Handling
Terminal clocks may drift due to long-term offline operation or hardware issues. This section defines the handling rules under clock drift conditions.
3.6.1 Clock Tolerance
The terminal MAY introduce tolerance when validating the validity period:
- For
not_before: May allow up to 5 minutes of early tolerance (acceptcurrent time ≥ not_before - 5min) - For
not_after: MUST NOT introduce tolerance (expired is expired)
Tolerance is used only to compensate for short-term clock offsets and SHOULD NOT be used to bypass validity period constraints.
3.6.2 Clock Trustworthiness
The terminal SHOULD detect the following clock anomalies and take protective measures:
- Significant clock backward (system clock jumps to the past > 1 hour): Reject validation requests until clock synchronization
- Significant clock forward (system clock jumps to the future > 24 hours): Reject validation requests until clock synchronization
3.7 Complete Flow Diagram
[Descriptor_Issuer] [Fay/iFay_Runtime] [Terminal/Protocol_Engine]
│ │ │
│── Issue AuthorizationDescriptor ────→│ │
│ (with digital signature) │ │
│ │ │
│ │── DescriptorSubmit ─────────────────→│
│ │ │── Verify signature + store
│ │←─ DescriptorSubmitResult ──────────── │
│ │ │
│ │── AuthRequest (with descriptor_id)──→│
│ │ │── 7-step validation
│ │←─ AuthResult (granted) ──────────────│
│ │ │── Create Session
│ │ │
│ │ 【Fay continuously accesses resource】│
│ │ │
│── Revoke RevocationStatement ─────────────────────────────────────────────────→│
│ │ │── Add to revocation list
│ │ │── Forcibly terminate related Session
